package monitor;

import java.util.*;

import bluetoothcomm.TwoWayComm;

public class Decoder implements StreamEventListener {
	private SerialComm serialComm;

	private NodeList globalNodeList = new NodeList();
	private ArrayList<NodeWithAngle> localNodeList = new ArrayList<NodeWithAngle>();
	private int[] channelInfoBuffer = new int[10];

	private int count = 0; // total line number should follows
	private int count1 = 0;// this is used for the remote device counter
	private int count2 = 0; // used for local device counter
	private int cur = 0; // reading line position

	private List<WholeBlockEventListener> blockEventListners = new ArrayList<WholeBlockEventListener>();

	public void addBlockListener(WholeBlockEventListener listener) {
		blockEventListners.add(listener);
	}

	public void removeBlockListener(AnglesEventListener listener) {
		blockEventListners.remove(listener);
	}

	protected void notifyBlockListeners(WholeBlockEvent e) {
		for (WholeBlockEventListener listener : blockEventListners) {
			listener.completeDataArriaved(e);
		}
	}

	public Decoder() {
		super();
	}

	public void initSerial() {
		// Natsuda modified this method
		serialComm = new SerialComm();
		// make some modifications here
		while(!serialComm.connect());
		serialComm.addStreamListener(this);

//		TwoWayComm.mySerialReader.addStreamListener(this);

	}

	public void closePebbleConnection() {

		serialComm.close();
	}

	private boolean dataFomatError = false;

	@Override
	public void streamAvailable(StreamEvent e) {

		if (cur == (count) && cur > 0) {
			notifyBlockListeners(new WholeBlockEvent(globalNodeList,
					localNodeList, channelInfoBuffer));
			//cur = 0;
		}

		if (dataFomatError) {
			StringTokenizer st = new StringTokenizer(e.getStr());
			if (st.countTokens() == 0) {
				// System.out.println("New Data Block start!!!");
				count = 0;
				count1 = 0;
				count2 = 0;
				cur = 0;
				globalNodeList.removeAllNodes();
				localNodeList.clear();
				for (int i = 0; i < channelInfoBuffer.length; i++)
					channelInfoBuffer[i] = 0;
				// everything should be reset here
				dataFomatError = false;
				return;

			} else
				return;

		}

		StringTokenizer st = new StringTokenizer(e.getStr());
		if (st.countTokens() == 0) {
			// System.out.println("New Data Block start!!!");
			count = 0;
			count1 = 0;
			count2 = 0;
			cur = 0;
			globalNodeList.removeAllNodes();
			localNodeList.clear();
			for (int i = 0; i < channelInfoBuffer.length; i++)
				channelInfoBuffer[i] = 0;
			// everything should be reset here

		} else if (count == 0) {
			count = Integer.parseInt(st.nextToken());
//			System.out.println(count + " totallines;");
		} else if (cur < count) {
			if (cur == 0) {
				count1 = Integer.parseInt(st.nextToken());
//				System.out.println("Count1 " + count1);
				cur++;
			} else if (cur < (count1 + 1)) {

				if (st.countTokens() >= 4) {
					int id = Integer.parseInt(st.nextToken());
					int ver = Integer.parseInt(st.nextToken());
					int pressed =Integer.parseInt(st.nextToken());
					int numNeibours = Integer.parseInt(st.nextToken());
//					System.out.print(id + " " + ver + " " + numNeibours + " ");
					Node node = new Node(id, ver,pressed);
					while (st.hasMoreTokens()) {
						int n = Integer.parseInt(st.nextToken());
//						System.out.print(n + " ");

						node.addNeibour(new Neibour(n));
					}
//					System.out.println();
					if (node.neibours.size() != numNeibours) {
						System.out.println("received data format error!");
						dataFomatError = true;
						return;

					}
					globalNodeList.addNode(node);
					cur++;
				}

			} else if (cur == (count1 + 1)) {
				count2 = Integer.parseInt(st.nextToken());
//				System.out.println("Count2=" + count2);
				if (count != count1 + count2 + 2) {

					System.err
							.println("The data format got from pebble is incorrect!!!!");
					dataFomatError = true;
					return;

				}
				cur++;
			} else if (cur < (count1 + count2 + 2)) {

				if (st.countTokens() >= 3) {
					int id = Integer.parseInt(st.nextToken());
					int angle = Integer.parseInt(st.nextToken());
					channelInfoBuffer[id] = Integer.parseInt(st
							.nextToken());

					localNodeList.add(new NodeWithAngle(id, angle, 0));
					cur++;
				}
			}
		}
	//	else if(cur == (count1 + count2 + 2 + 10)) {
	//		cur++;
			//System.out.println("collision " + Integer.parseInt(st.nextToken()));
	//	}

	}

	public static void main(String args[]) {

		Decoder decoder = new Decoder();
		decoder.initSerial();

	}

}
